﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace ReprojectWebMercator
{
    public class Matrix
    {
        public float[] Mat;

        public Matrix() { }
        public Matrix(double v11, double v12, double v13, double v14,
            double v21, double v22, double v23, double v24,
            double v31, double v32, double v33, double v34,
            double v41, double v42, double v43, double v44)
        {
            Mat = new float[16]{
                 (float)v11, (float)v12, (float)v13,  (float)v14,
            (float)v21, (float)v22, (float)v23, (float)v24,
            (float)v31, (float)v32, (float)v33, (float)v34,
            (float)v41, (float)v42, (float)v43, (float)v44
            };
        }
        public static Matrix FromColumns(double v11, double v12, double v13, double v14,
            double v21, double v22, double v23, double v24,
            double v31, double v32, double v33, double v34,
            double v41, double v42, double v43, double v44)
        {
            var m= new Matrix();
            m.Mat= new float[16]{
                 (float)v11, (float)v21, (float)v31,  (float)v41,
            (float)v12, (float)v22, (float)v32, (float)v42,
            (float)v13, (float)v23, (float)v33, (float)v43,
            (float)v14, (float)v24, (float)v34, (float)v44
            };
            return m;
        }
        public Matrix(string str)
        {
            var jvalue=JsonConvert.DeserializeObject(str) as JToken;
            Mat = new float[16];
            for(var i=0;i<16; i++)
            {
                Mat[i] = float.Parse(((Newtonsoft.Json.Linq.JValue)(jvalue[i.ToString()] as JToken)).Value.ToString());
            }
        }

        internal vec4 Multiply(vec4 b)
        {
            var x = Mat[0] * b.x + Mat[4] * b.y + Mat[8] * b.z + Mat[12] * b.w;
            var y = Mat[0 + 1] * b.x + Mat[4 + 1] * b.y + Mat[8 + 1] * b.z + Mat[12 + 1] * b.w;
            var z = Mat[0 + 2] * b.x + Mat[4 + 2] * b.y + Mat[8 + 2] * b.z + Mat[12 + 2] * b.w;
            var w = Mat[0 + 3] * b.x + Mat[4 + 3] * b.y + Mat[8 + 3] * b.z + Mat[12 + 3] * b.w;
            return new vec4(x, y, z, w);
        }
        internal vec4 Multiply2(vec4 b)
        {
            var x = Mat[0] * b.x + Mat[1] * b.y + Mat[2] * b.z + Mat[3] * b.w;
            var y = Mat[0 + 4] * b.x + Mat[4 + 1] * b.y + Mat[6] * b.z + Mat[7] * b.w;
            var z = Mat[8] * b.x + Mat[9] * b.y + Mat[10] * b.z + Mat[11] * b.w;
            var w = Mat[12] * b.x + Mat[13] * b.y + Mat[14] * b.z + Mat[15] * b.w;
            return new vec4(x, y, z, w);
        }


        public static vec4 operator *(Matrix t, vec4 v1)
        {
            return t.Multiply(v1);
        }
    }
}
